home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / libsock / os2serial.c < prev    next >
C/C++ Source or Header  |  1997-08-11  |  11KB  |  393 lines

  1. /* os2serial.c: tty line interface code for Pilot comms under OS/2
  2.  *
  3.  * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski.
  4.  * This is free software, licensed under the GNU Public License V2.
  5.  * See the file COPYING for details.
  6.  */
  7.  
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <stdio.h>
  11. #include <io.h>
  12. #include "pi-source.h"
  13. #include "pi-socket.h"
  14. #include "pi-serial.h"
  15. #include "pi-slp.h"
  16. #include "pi-syspkt.h"
  17. #include "pi-padp.h"
  18.  
  19. #ifdef HAVE_SYS_IOCTL_COMPAT_H
  20. #include <sys/ioctl_compat.h>
  21. #endif
  22.  
  23. #define INCL_BASE
  24. #define INCL_DOSFILEMGR    /* File System values */
  25. #define INCL_DOSDEVIOCTL   /* DosDevIOCtl values */
  26. #define INCL_DOSDEVICES    /* DosDevice   values */
  27. #include <os2.h>
  28.  
  29. static int so_changebaud(struct pi_socket *ps);
  30. static int so_close(struct pi_socket *ps);
  31. static int pi_socket_set_timeout(struct pi_socket *ps, int read_timeout, 
  32.                           int write_timeout);
  33. static int so_write(struct pi_socket *ps);
  34. static int so_read(struct pi_socket *ps, int timeout);
  35.  
  36. int pi_serial_open(struct pi_socket *ps, struct pi_sockaddr * addr, int addrlen)
  37. {
  38.   int rc;
  39.   HFILE fd;
  40.   unsigned long action;
  41.   int filesize=0;
  42.   char * tty = addr->pi_device;
  43.   if ((!tty) || !strlen(tty))
  44.     tty = getenv("PILOTPORT");
  45.   if (!tty)
  46.     tty = "<Null>";
  47.   
  48.  
  49.   /* open the device */
  50.   rc=DosOpen(tty, /* the device */
  51.              &fd, /* the file descriptor returned */
  52.              &action, /* the action taken */
  53.              filesize, /* the size of the file */
  54.              FILE_NORMAL, /* file permissions mode, not the same as UNIX */
  55.              OPEN_ACTION_OPEN_IF_EXISTS, /* file open action */
  56.              OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, /* open mode */
  57.              0); /* extended attributes */
  58.   if (rc)
  59.     {
  60.       switch (rc)
  61.         {
  62.         case    2:         /* ERROR_FILE_NOT_FOUND  */
  63.           errno=ENOENT;
  64.           break;
  65.         case    3:         /* ERROR_PATH_NOT_FOUND  */
  66.           errno=ENOTDIR;
  67.           break;
  68.         case    4:         /* ERROR_TOO_MANY_OPEN_FILES  */
  69.           errno=EMFILE;
  70.           break;
  71.         case    5:         /* ERROR_ACCESS_DENIED  */
  72.           errno=EACCES;
  73.           break;
  74.         case    32:        /* ERROR_SHARING_VIOLATION  */
  75.           errno=EBUSY;
  76.           break;
  77.         case    82:        /* ERROR_CANNOT_MAKE  */
  78.           errno=EEXIST;
  79.           break;
  80.         case    99:        /* ERROR_DEVICE_IN_USE  */
  81.           errno=EBUSY;
  82.           break;
  83.         case    112:       /* ERROR_DISK_FULL  */
  84.           errno=ENOSPC;
  85.           break;
  86.         case    87:        /* ERROR_INVALID_PARAMETER  */
  87.           errno=EINVAL;
  88.           break;
  89.         default:
  90.           errno=-ENOMSG;
  91.           break;
  92.         }
  93.       return(-1);
  94.     }
  95.     
  96.   ps->mac->fd=_imphandle(fd);         /* Let EMX know about this handle */
  97.   ps->mac->fd=dup2(ps->mac->fd, ps->sd); /* Substitute serial connection for
  98.                                             original NUL handle */
  99.   
  100.   ps->serial_changebaud = so_changebaud;
  101.   so_changebaud(ps);
  102.   pi_socket_set_timeout(ps,-1,600);
  103.  
  104.   ps->serial_close = so_close;
  105.   ps->serial_read = so_read;
  106.   ps->serial_write = so_write;
  107.   
  108. #ifndef NO_SERIAL_TRACE
  109.   if (ps->debuglog) {
  110.     ps->debugfd = open(ps->debuglog,O_WRONLY|O_CREAT,0666);
  111.     /* This sequence is magic used by my trace analyzer - kja */
  112.     write(ps->debugfd, "\0\1\0\0\0\0\0\0\0\0", 10);
  113.   }
  114. #endif
  115.   return(fd);  
  116. }
  117.  
  118. static int so_changebaud(struct pi_socket *ps)
  119. {
  120.   int param_length;
  121.   int rc, baudrate;
  122.   unsigned char linctrl[3] = {8,0,0};
  123.  
  124.   baudrate = ps->rate;
  125.  
  126.   param_length=sizeof(baudrate);
  127.   rc=DosDevIOCtl(ps->mac->fd, /* file decsriptor */
  128.                  IOCTL_ASYNC, /*asyncronous change */
  129.                  ASYNC_SETBAUDRATE, /* set the baudrate */
  130.                  &baudrate, /* pointer to the baudrate */
  131.                  param_length, /* length of the previous parameter */
  132.                  (unsigned long *)¶m_length, /* max length of data ret */
  133.                  NULL, /* data to be sent */
  134.                  0, /* length of data */
  135.                  NULL); /* length of data returned */
  136.  
  137.   /* also set the port to 8N1 as OS/2 defaults to some braindead values */
  138.   if (!rc)   /* but only if the previous operation succeeded */
  139.     {
  140.       param_length = 3; /* 3 bytes for line control */
  141.       rc=DosDevIOCtl(ps->mac->fd, /* file decsriptor */
  142.                      IOCTL_ASYNC, /*asyncronous change */
  143.                      ASYNC_SETLINECTRL, /* set the line controls */
  144.                      linctrl, /* pointer to the configuration */
  145.                      param_length, /* length of the previous parameter */
  146.                      (unsigned long *)¶m_length, /* max length of params */
  147.                      NULL, /* data to be returned */
  148.                      0, /* length of data */
  149.                      NULL); /* length of data returned */
  150.     }
  151.  
  152.  
  153.   if (rc)
  154.     {
  155.       switch (rc)
  156.         {
  157.         case    1:         /* ERROR_INVALID_FUNCTION */
  158.           errno=ENOTTY;
  159.           break;
  160.         case    6:         /* ERROR_INVALID_HANDLE */
  161.           errno=EBADF;
  162.           break;
  163.         case    87:        /* ERROR_INVALID_PARAMETER */
  164.           errno=EINVAL;
  165.           break;
  166.         default:
  167.           errno=-ENOMSG;
  168.           break;
  169.         }
  170.       return(-1);
  171.     }
  172.   /* this pause seems necessary under OS2 to let the serial
  173.      port realign itself */
  174.   sleep(1);
  175. #ifdef OS2_DEBUG
  176.   fprintf(stderr,"set baudrate to %d\n",baudrate);
  177. #endif
  178.   return(0);
  179. }
  180.  
  181. static int so_close(struct pi_socket *ps)
  182. {
  183. #ifndef NO_SERIAL_TRACE
  184.   if (ps->debugfd)
  185.     close(ps->debugfd);  
  186. #endif
  187.  
  188.   DosClose(ps->mac->fd);
  189.   return(0);
  190. }
  191.  
  192.  
  193. /* 
  194.  * values for read_timeout and write_timeout 
  195.  * 0           = infinite timeout
  196.  * 1 to 65535  = timeout in seconds
  197.  * -1          = dont change timeout
  198.  */
  199. static int pi_socket_set_timeout(struct pi_socket *ps, int read_timeout, 
  200.                           int write_timeout)
  201. {
  202.   int param_length, ret_len;
  203.   int rc;
  204.   int newtimeout;
  205.   DCBINFO devinfo;
  206.  
  207.   if ((ps->os2_read_timeout==read_timeout || read_timeout==-1) && 
  208.       (ps->os2_write_timeout==write_timeout || write_timeout==-1))
  209.     return(0);
  210.  
  211.   ret_len=sizeof(DCBINFO);
  212.   rc=DosDevIOCtl(ps->mac->fd, /* file decsriptor */
  213.                  IOCTL_ASYNC, /*asyncronous change */
  214.                  ASYNC_GETDCBINFO, /* get device control block info */
  215.                  NULL, /*  */
  216.                  0, /* length of the previous parameter */
  217.                  NULL, /* max length of data ret */
  218.                  &devinfo, /* data to be recieved */
  219.                  ret_len, /* length of data */
  220.                  (unsigned long *)&ret_len); /* length of data returned */
  221.   if (rc)
  222.     goto error;
  223.  
  224.   if (read_timeout!=-1)
  225.     {
  226.       if (read_timeout==0)
  227.         {
  228.       devinfo.usReadTimeout=65535;
  229.     }
  230.       else
  231.         {
  232.           newtimeout=read_timeout -0.1;
  233.           if (newtimeout>65535)
  234.             newtimeout=65535;
  235.           devinfo.usReadTimeout=newtimeout;
  236.         }
  237.     }
  238.   if (write_timeout==-1)
  239.     {
  240.       if (write_timeout==0)
  241.         {
  242.           devinfo.fbTimeout |=0x01;
  243.         }
  244.       else
  245.         {
  246.           devinfo.fbTimeout &= 0xFE;
  247.           newtimeout=write_timeout;
  248.           if (newtimeout>65535)
  249.             newtimeout=65535;
  250.           devinfo.usWriteTimeout=newtimeout;
  251.         }
  252.     }
  253.   param_length=sizeof(DCBINFO);
  254.   rc=DosDevIOCtl(ps->mac->fd, /* file decsriptor */
  255.                  IOCTL_ASYNC, /*asyncronous change */
  256.                  ASYNC_SETDCBINFO, /* get device control block info */
  257.                  &devinfo, /* parameters to set  */
  258.                  param_length, /* length of the previous parameter */
  259.                  (unsigned long *)¶m_length, /* max length of parameters */
  260.                  NULL, /* data to be recieved */
  261.                  0, /* length of data */
  262.                  NULL); /* length of data returned */
  263.  
  264.  
  265.        
  266. error:
  267.   if (rc)
  268.     {
  269.       switch (rc)
  270.         {
  271.         case    1:         /* ERROR_INVALID_FUNCTION */
  272.           errno=ENOTTY;
  273.           break;
  274.         case    6:         /* ERROR_INVALID_HANDLE */
  275.           errno=EBADF;
  276.           break;
  277.         case    87:        /* ERROR_INVALID_PARAMETER */
  278.           errno=EINVAL;
  279.           break;
  280.         default:
  281.           errno=-ENOMSG;
  282.           break;
  283.         }
  284.       return(-1);
  285.     }
  286.   if (read_timeout!=-1)
  287.     ps->os2_read_timeout=read_timeout;
  288.   if (write_timeout!=-1)
  289.     ps->os2_write_timeout=write_timeout;
  290. #ifdef OS2_DEBUG
  291.   // fprintf(stderr,"set read_timeout to %d\n",read_timeout);
  292.   // fprintf(stderr,"set write_timeout to %d\n",write_timeout);
  293. #endif
  294.   return(0);
  295. }  
  296.  
  297. static int so_write(struct pi_socket *ps)
  298. {
  299.   struct pi_skb *skb;
  300.   int nwrote, len;
  301. #ifndef NO_SERIAL_TRACE
  302.   int i;
  303. #endif
  304.   int rc;
  305.  
  306.   if (ps->txq) {
  307.   
  308.     ps->busy++;
  309.  
  310.     skb = ps->txq;
  311.     ps->txq = skb->next;
  312.  
  313.     len = 0;
  314.     while (len<skb->len) {
  315.       nwrote = 0;
  316.       rc=DosWrite(ps->mac->fd,skb->data,skb->len,(unsigned long *)&nwrote);
  317.       if (nwrote<=0)
  318.         break; /* transmission failure */
  319.       len += nwrote;
  320.     }
  321. #ifndef NO_SERIAL_TRACE
  322.     if (ps->debuglog)
  323.       for (i=0;i<skb->len;i++) {
  324.         write(ps->debugfd, "2", 1);
  325.         write(ps->debugfd, skb->data+i, 1);
  326.       }
  327. #endif
  328.     ps->tx_bytes += skb->len;
  329.     free(skb);
  330.  
  331.     ps->busy--;
  332.     
  333.     return 1;
  334.   }
  335.   return 0;
  336. }
  337.  
  338. static int so_read(struct pi_socket *ps, int timeout)
  339. {
  340.   int r;
  341.   unsigned char *buf;
  342. #ifndef NO_SERIAL_TRACE
  343.   int i;
  344. #endif
  345.   int rc;
  346.  
  347.   /* FIXME: if timeout == 0, wait forever for packet, otherwise wait till
  348.      timeout tenth-of-seconds */
  349.  
  350.   /* for OS2, timeout of 0 is almost forever, only 1.8 hours */
  351.   /* if no timeout is set at all, the timeout defaults to 1 minute */
  352.   rc=pi_socket_set_timeout(ps,timeout,-1);
  353.   if (rc==-1)
  354.     {
  355.       fprintf(stderr,"error setting timeout, old timeout used\n");
  356.     }
  357.  
  358.   pi_serial_flush(ps);              /* We likely want to be in sync with tx */
  359.   if (!ps->mac->expect) slp_rx(ps);  /* let SLP know we want a packet */
  360.  
  361.   while (ps->mac->expect) {
  362.     buf = ps->mac->buf;
  363.  
  364.     while (ps->mac->expect) {
  365.       rc=DosRead(ps->mac->fd,buf,ps->mac->expect,(unsigned long *)&r);
  366.       if (rc)
  367.       {
  368.         /* otherwise throw out any current packet and return */
  369. #ifdef DEBUG
  370.         fprintf(stderr, "Serial RX: timeout\n");
  371. #endif
  372.         ps->mac->state = ps->mac->expect = 1;
  373.         ps->mac->buf = ps->mac->rxb->data;
  374.         ps->rx_errors++;
  375.         return 0;
  376.       }
  377. #ifndef NO_SERIAL_TRACE
  378.       if (ps->debuglog)
  379.         for (i=0;i<r;i++) {
  380.           write(ps->debugfd, "1", 1);
  381.           write(ps->debugfd, buf+i, 1);
  382.         }
  383. #endif
  384.       ps->rx_bytes += r;
  385.       buf += r;
  386.       ps->mac->expect -= r;
  387.     }
  388.     slp_rx(ps);
  389.   }
  390.   return 0;
  391. }
  392.  
  393.